/*
#Copyright (c) 2013, Philippe Bordron <philippe.bordron@gmail.com>
#
# This file is part of SIPPER.
#
# DCC is free software: you can redistribute it and/or modify
# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU LESSER GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# along with SIPPER.  If not, see <http://www.gnu.org/licenses/>
*/
package combi.wip.sipper.modeling.metabolicNetworks;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import combi.wip.sipper.modeling.reactions.Reaction;

public abstract class MetabolicNetwork<C,R extends Reaction<C>> {

	protected Map<String, C> compoundSet;
	protected Map<String,Reaction<C>> reactionSet;
	

	public void init() {
		compoundSet = new HashMap<String,C>();
		reactionSet = new HashMap<String, Reaction<C>>();
	}
	
	public abstract void addCompound(C cpd);
	public abstract Collection<C> getCompounds(Reaction<C> reaction);
	public abstract Collection<C> getSubstrats(Reaction<C> reaction);
	public abstract Collection<C> getProducts(Reaction<C> reaction);
	public abstract void removeCompound(C cpd);

	public abstract void addReaction(Reaction<C> reaction);
	public abstract void updateReaction(Reaction<C> reaction);
	public abstract Collection<Reaction<C>> getReactions(C cpd);
	public abstract Collection<Reaction<C>> whichProduce(C cpd);
	public abstract Collection<Reaction<C>> whichConsume(C cpd);
	public abstract void removeReaction(Reaction<C> reaction);
	
	public void deepCopy(MetabolicNetwork<C, Reaction<C>> meta) {
		compoundSet = new HashMap<String,C>();
		for(C c : meta.getCompoundSet())
		{
			this.addCompound(c);
		}
		reactionSet = new HashMap<String,Reaction<C>>();
		for (Reaction<C> r : meta.getReactionSet())
		{
			this.addReaction(r);
		}
		
	}

	public Collection<C> getCompoundSet() {
		return compoundSet.values();
	}

	public C getCompound(String id)
	{
		return compoundSet.get(id);
	}
	
	public Collection<Reaction<C>> getReactionSet() {
		return reactionSet.values();
	}
	
	public Reaction<C> getReaction(String id)
	{
		return reactionSet.get(id);
	}
	
	protected Collection<Reaction<C>> checkAndRemoveReactions()
	{
		Set<Reaction<C>> result = new HashSet<Reaction<C>>();//reactions incorrectes
		for (Reaction<C> r : this.getReactionSet())
		{
			if (!r.isValid())
			{
				result.add(r);
			}
		}
		for (Reaction<C> r: result)
		{
			this.removeReaction(r);
		}
		return result;
	}
	
	public void clear()
	{
		compoundSet.clear();
		reactionSet.clear();
	}
	
	public String toString()
	{
		return this.getCompoundSet().toString() + ", " + this.getReactionSet().toString();
	}

	public Collection<Reaction<C>> nextReactions(Reaction<C> r)
	{
		Collection<Reaction<C>> result = new HashSet<Reaction<C>>();
		for (C c : this.getProducts(r))
		{
			result.addAll(this.whichConsume(c));
		}
		result.remove(r);
		return result;
	}
	
	public Collection<Reaction<C>> previousReactions(Reaction<C> r)
	{
		Collection<Reaction<C>> result = new HashSet<Reaction<C>>();
		for (C c : this.getSubstrats(r))
		{
			result.addAll(this.whichProduce(c));
		}
		result.remove(r);
		return result;
	}
	
	public Collection<C> nextCompounds(C c)
	{
		Collection<C> result = new HashSet<C>();
		for (Reaction<C> r : this.whichConsume(c))
		{
			result.addAll(this.getProducts(r));
		}
		result.remove(c);
		return result;
	}
	
	public Collection<C> previousCompounds(C c)
	{
		Collection<C> result = new HashSet<C>();
		for (Reaction<C> r : this.whichProduce(c))
		{
			result.addAll(this.getSubstrats(r));
		}
		result.remove(c);
		return result;
	}
}
